package de.xelerity.geolessi.types.poi;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import de.xelerity.geolessi.srv.mixed.AbfahrtszeitComperator;
import de.xelerity.helper.DateFunktionen;
import de.xelerity.helper.StringFunktionen;

public abstract class AbAnkunft implements Serializable {

	private static final long serialVersionUID = 1632143203037570584L;
	private String AbAnfahrtzeit = ""; // Abfahrtzeit nach Fahrplan
	private String AbAnfahrtzeitRealTime = ""; // reale Abfahrtzeit inkl.
	// Verspaetung
	private String AbAnfahrtzeitOffset = ""; // Abfahrt in X mins
	private String SpezialMessage = ""; // Allgemeine Verbindungshinweise

	private static Log log = LogFactory.getLog(AbAnkunft.class);

	protected String getAbAnfahrtzeit() {
		return (AbAnfahrtzeit == null ? "" : AbAnfahrtzeit.trim());
	}

	protected void setAbAnfahrtzeit(String abfahrtzeitfahrplan) {
		AbAnfahrtzeit = abfahrtzeitfahrplan;
	}

	protected String getAbAnfahrtzeitOffset() {
		return (AbAnfahrtzeitOffset == null ? "" : AbAnfahrtzeitOffset.trim());
	}

	protected void setAbAnfahrtzeitOffset(String offset) {
		AbAnfahrtzeitOffset = offset;
	}

	protected String getAbAnfahrtzeitRealTime() {
		return AbAnfahrtzeitRealTime == null ? "" : AbAnfahrtzeitRealTime.trim();
	}

	// 12:23
	protected void setAbAnfahrtzeitRealTime(String abfahrtzeitRealTime) {

		if (StringFunktionen.isEmptyTrimed(abfahrtzeitRealTime)) {
			abfahrtzeitRealTime = "<null>";
			return;
		} else
			abfahrtzeitRealTime = abfahrtzeitRealTime.trim();

		if (abfahrtzeitRealTime.matches("^[0-9]:[0-9][0-9]*$"))
			abfahrtzeitRealTime = "0" + abfahrtzeitRealTime;

		if (abfahrtzeitRealTime.matches("^[0-9]+:[0-9]$"))
			abfahrtzeitRealTime = abfahrtzeitRealTime + "0";

		AbAnfahrtzeitRealTime = abfahrtzeitRealTime;
	}

	// /////////////////////////////////////////////////////////////////////////////////////

	public String toString() {
		String diff = "";
		if (!getAbAnfahrtzeitRealTime().equalsIgnoreCase(getAbAnfahrtzeit())) {
			diff = "#";
		}
		return getAbAnfahrtzeitRealTime() + "/" + getAbAnfahrtzeit() + diff + "/" + getAbAnfahrtzeitOffset();
	}

	public boolean equals(Object p) {
		if (p == null) {
			return false;
		}
		if (p instanceof Abfahrt)
			return ((Abfahrt) p).getAbfahrtzeitRealTime().equalsIgnoreCase(this.getAbAnfahrtzeitRealTime());
		if (p instanceof Ankunft)
			return ((Ankunft) p).getAnkunftzeitRealTime().equalsIgnoreCase(this.getAbAnfahrtzeitRealTime());
		if (p instanceof AbAnkunft)
			return ((AbAnkunft) p).getAbAnfahrtzeitRealTime().equalsIgnoreCase(this.getAbAnfahrtzeitRealTime());

		return false;
	}

	public int hashCode() {
		return getAbAnfahrtzeitRealTime().hashCode();
	}

	public boolean isValid() {

		if (StringFunktionen.isEmptyTrimed(getAbAnfahrtzeit()) && !StringFunktionen.isEmptyTrimed(getAbAnfahrtzeitRealTime())) {
			setAbAnfahrtzeit(getAbAnfahrtzeitRealTime());
		}

		if (!StringFunktionen.isEmptyTrimed(getAbAnfahrtzeit()) && StringFunktionen.isEmptyTrimed(getAbAnfahrtzeitRealTime())) {
			setAbAnfahrtzeitRealTime(getAbAnfahrtzeit());
		}
		return (getAbAnfahrtzeitRealTime().matches("^[0-9][0-9]*:[0-9][0-9]*$"));
	}

	// return Offset in Minutes
	public static int calcOffset(long pCurrentTime, String TargetTime /* 12:23 */, Date pDatum /*
																															 * 12.12
																															 * .2012
																															 */) throws Exception {
		Ankunft dummy = new Ankunft();
		dummy.setAnkunftzeitRealTime(TargetTime);
		if (!dummy.isValid()) {
			throw new Exception("kein valides Zeitformat");
		}

		if (pDatum == null) {
			dummy.calcOffset(pCurrentTime);
			return new Integer(dummy.getAbAnfahrtzeitOffset()).intValue();
		}

		GregorianCalendar lTime = new GregorianCalendar();
		GregorianCalendar lNow = new GregorianCalendar();
		lNow.setTime(new Date(pCurrentTime));
		lNow.set(Calendar.SECOND, 00);

		String[] split = dummy.getAnkunftzeitRealTime().split(":");
		lTime.setTime(pDatum);
		lTime.set(Calendar.HOUR_OF_DAY, Integer.parseInt(split[0]));
		lTime.set(Calendar.MINUTE, Integer.parseInt(split[1]));
		lTime.set(Calendar.SECOND, 00);

		if (lNow.get(Calendar.HOUR_OF_DAY) == lTime.get(Calendar.HOUR_OF_DAY)
				&& lNow.get(Calendar.MINUTE) == lTime.get(Calendar.MINUTE)
				&& DateFunktionen.DateEqual(new Date(pCurrentTime), pDatum)) {

			return 0;
		}

		long M1 = lNow.getTimeInMillis();
		long M2 = lTime.getTimeInMillis();
		int mins = (int) (Math.round(Math.abs(M2 - M1) / 1000.0 / 60.0));

		if (lNow.getTimeInMillis() < lTime.getTimeInMillis())
			return mins;
		else
			return -mins;
	}

	public void calcOffset(long pCurrentTime) {
		try {
			if (!isValid()) {
				throw new Exception("kein valides Zeitformat");
			}
			GregorianCalendar lTime = new GregorianCalendar();
			GregorianCalendar lNow = new GregorianCalendar();

			// System.out.println("now:" + new Date(pCurrentTime).toString());

			lNow.setTime(new Date(pCurrentTime));
			lNow.set(Calendar.SECOND, 00);

			String[] split = getAbAnfahrtzeitRealTime().split(":");
			lTime.setTime(new Date(pCurrentTime));
			lTime.set(Calendar.HOUR_OF_DAY, Integer.parseInt(split[0]));
			lTime.set(Calendar.MINUTE, Integer.parseInt(split[1]));
			lTime.set(Calendar.SECOND, 00);

			if (lNow.get(Calendar.HOUR_OF_DAY) == lTime.get(Calendar.HOUR_OF_DAY)
					&& lNow.get(Calendar.MINUTE) == lTime.get(Calendar.MINUTE)) {
				this.setAbAnfahrtzeitOffset("0");
				return;
			}

			if (!new AbfahrtszeitComperator(pCurrentTime).isFuture(getAbAnfahrtzeitRealTime())) {

				long timeInMillis = lTime.getTimeInMillis();
				timeInMillis = timeInMillis + 24 * 60 * 60 * 1000;
				lTime.setTimeInMillis(timeInMillis);
			}

			// System.out.println("abf:" + new
			// Date(lTime.getTimeInMillis()).toString());

			long M1 = lNow.getTimeInMillis();
			long M2 = lTime.getTimeInMillis();
			int mins = (int) (Math.round(Math.abs(M2 - M1) / 1000.0 / 60.0));

			if (mins == 0 || new AbfahrtszeitComperator(pCurrentTime).isFuture(lTime.getTimeInMillis())) {
				this.setAbAnfahrtzeitOffset("" + mins);
			} else {
				this.setAbAnfahrtzeitOffset("-" + mins);
			}
		} catch (Throwable e) {
			log.error("cannot calc offset:" + this.toString(), e);
		}
	}

	public String getSpezialMessage() {
		return SpezialMessage == null ? "" : SpezialMessage.trim();
	}

	public void setSpezialMessage(String spezialMessage) {
		SpezialMessage = spezialMessage;
	}

}
